<template>
  <view class="xen-dynamic-form-card" :class="{ 'has-footer': showFooter }">
    <view class="form-card">
      <!-- 表单头部 -->
      <view v-if="showHeader" class="form-header">
        <text class="form-title">{{ title }}</text>
        <text v-if="subtitle" class="form-subtitle">{{ subtitle }}</text>
      </view>

      <!-- 表单内容区域 -->
      <view class="form-content">
        <!-- 配置驱动的动态表单 -->
        <view
          v-for="section in sections"
          :key="section.key"
          class="form-section"
        >
          <view v-if="section.title" class="section-title">{{
            section.title
          }}</view>

          <view
            v-for="field in section.fields"
            :key="field.key"
            class="form-item"
          >
            <!-- 字段标签 -->
            <text v-if="field.label" class="form-label">
              <text v-if="field.required" class="required">*</text>
              {{ field.label }}
            </text>

            <!-- 只读字段 -->
            <view v-if="field.type === 'readonly'" class="form-readonly">
              <!-- 身份证有效期特殊处理：如果显示状态为长期有效，显示为"长期有效" -->
              <template
                v-if="
                  field.key === 'idCardExpiryDate' &&
                  field.supportLongTerm &&
                  idCardExpiryDisplayState === 'long-term'
                "
              >
                <text class="readonly-text long-term-text">长期有效</text>
              </template>
              <!-- 正常的只读字段显示 -->
              <template v-else>
                <text class="readonly-text">
                  {{ modelValue[field.key] || field.placeholder }}
                </text>
              </template>
            </view>

            <!-- 输入框 -->
            <input
              v-else-if="field.type === 'input'"
              class="form-input"
              :class="{
                'has-error': errors[field.key],
                disabled: field.disabled,
                readonly: field.readonly,
              }"
              type="text"
              :value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :maxlength="field.maxlength"
              :disabled="field.disabled"
              :readonly="field.readonly"
              @input="handleFieldChange(field.key, $event.detail.value)"
              @blur="handleFieldBlur(field.key)"
            />

            <!-- 额外信息显示 -->
            <text
              v-if="field.extraInfo && getExtraInfo(field)"
              class="extra-info"
            >
              {{ getExtraInfo(field) }}
            </text>

            <!-- 文本域 -->
            <textarea
              v-else-if="field.type === 'textarea'"
              class="form-textarea"
              :class="{
                'has-error': errors[field.key],
                disabled: field.disabled,
                readonly: field.readonly,
              }"
              :value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :maxlength="field.maxlength"
              :disabled="field.disabled"
              :readonly="field.readonly"
              @input="handleFieldChange(field.key, $event.detail.value)"
              @blur="handleFieldBlur(field.key)"
            />

            <!-- 数字输入框 -->
            <XenNumberInput
              v-else-if="field.type === 'number'"
              :modelValue="modelValue[field.key]"
              :placeholder="field.placeholder"
              :hasError="!!errors[field.key]"
              :disabled="field.disabled"
              :readonly="field.readonly"
              :min="field.min"
              :max="field.max"
              :step="field.step"
              :precision="field.precision"
              :allowNegative="field.allowNegative"
              @update:modelValue="
                (value) => handleFieldChange(field.key, value)
              "
              @blur="handleFieldBlur(field.key)"
            />

            <!-- 选择器 - APP端使用专用组件 -->
            <!-- #ifdef APP-PLUS -->
            <XenAppSelector
              v-else-if="field.type === 'picker'"
              :model-value="modelValue[field.key]"
              :options="field.optionsData || field.options || []"
              :placeholder="
                field.disabled && !modelValue[field.key]
                  ? getDisabledPlaceholder(field)
                  : field.placeholder
              "
              :disabled="field.disabled"
              :has-error="!!errors[field.key]"
              :option-text-field="field.rangeKey || 'text'"
              :option-value-field="'value'"
              @update:model-value="
                (value) => handleAppSelectorChange(field.key, value, field)
              "
              @change="
                (value, option) =>
                  handleAppSelectorOptionChange(field.key, value, option, field)
              "
            />
            <!-- #endif -->

            <!-- 选择器 - 其他平台使用原生picker -->
            <!-- #ifndef APP-PLUS -->
            <picker
              v-else-if="field.type === 'picker'"
              class="form-picker"
              :class="{
                'has-error': errors[field.key],
                disabled: field.disabled,
              }"
              mode="selector"
              :range="field.options || []"
              :disabled="field.disabled"
              @change="handlePickerChange(field.key, $event)"
            >
              <view
                class="picker-content"
                :class="{ disabled: field.disabled }"
              >
                <text class="picker-text" :class="{ disabled: field.disabled }">
                  {{
                    field.disabled && !modelValue[field.key]
                      ? getDisabledPlaceholder(field)
                      : getPickerDisplay(field)
                  }}
                </text>
                <uni-icons
                  type="down"
                  size="14"
                  :color="field.disabled ? '#ccc' : '#999'"
                ></uni-icons>
              </view>
            </picker>
            <!-- #endif -->

            <!-- 字段提示信息 -->
            <text v-if="field.tips" class="field-tips">
              {{ field.tips }}
            </text>

            <!-- 日期时间选择器 -->
            <view
              v-else-if="field.type === 'datetime'"
              class="datetime-picker-wrapper"
            >
              <uni-datetime-picker
                v-model="modelValue[field.key]"
                type="datetime"
                :class="{ 'has-error': errors[field.key] }"
                :placeholder="field.placeholder"
                @change="handleDateTimeChange(field.key, $event)"
                @show="handleDateTimePickerOpen"
                @hide="handleDateTimePickerClose"
                @confirm="handleDateTimePickerClose"
                @cancel="handleDateTimePickerClose"
                @maskClick="handleDateTimePickerClose"
              />
            </view>

            <!-- 日期选择器 -->
            <view
              v-else-if="field.type === 'date'"
              class="datetime-picker-wrapper"
            >
              <uni-datetime-picker
                v-model="modelValue[field.key]"
                type="date"
                :class="{ 'has-error': errors[field.key] }"
                :placeholder="field.placeholder"
                @change="handleDateTimeChange(field.key, $event)"
                @show="handleDateTimePickerOpen"
                @hide="handleDateTimePickerClose"
                @confirm="handleDateTimePickerClose"
                @cancel="handleDateTimePickerClose"
                @maskClick="handleDateTimePickerClose"
              />
            </view>

            <!-- 原生日期选择器 - APP端使用专用组件 -->
            <!-- #ifdef APP-PLUS -->
            <XenAppDatePicker
              v-else-if="field.type === 'native-date'"
              :model-value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :start-date="field.startDate"
              :end-date="field.endDate"
              :disabled="field.disabled"
              :has-error="!!errors[field.key]"
              :format="field.dateFormat"
              @update:model-value="
                (value) => handleFieldChange(field.key, value)
              "
              @change="(value) => handleDateTimeChange(field.key, value)"
            />
            <!-- #endif -->

            <!-- 原生日期选择器 - 其他平台使用原生组件 -->
            <!-- #ifndef APP-PLUS -->
            <XenDatePicker
              v-else-if="field.type === 'native-date'"
              :model-value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :start-date="field.startDate"
              :end-date="field.endDate"
              :disabled="field.disabled"
              :has-error="!!errors[field.key]"
              :format="field.dateFormat"
              @update:model-value="
                (value) => handleFieldChange(field.key, value)
              "
              @change="(value) => handleDateTimeChange(field.key, value)"
            />
            <!-- #endif -->

            <!-- 部门选择器 -->
            <XenDepartmentPicker
              v-else-if="field.type === 'department-picker'"
              :model-value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :popup-title="field.popupTitle || '选择部门'"
              :department-data="field.departmentData || []"
              :class="{ 'has-error': errors[field.key] }"
              @update:model-value="
                (value) => handleFieldChange(field.key, value)
              "
              @change="
                (value, item) =>
                  handleDepartmentPickerChange(field.key, value, item)
              "
              @popup-open="handleDepartmentPickerOpen"
              @popup-close="handleDepartmentPickerClose"
            />

            <!-- 自动补全输入框 -->
            <XenAutoComplete
              v-else-if="field.type === 'autocomplete'"
              :model-value="modelValue[field.key]"
              :placeholder="field.placeholder"
              :options="field.optionsData || []"
              :has-error="!!errors[field.key]"
              :search-api="field.searchApi"
              :min-search-length="field.minSearchLength || 1"
              :debounce-time="field.debounceTime || 300"
              @update:model-value="
                (value) => handleFieldChange(field.key, value)
              "
              @change="
                (value, option) =>
                  handleAutoCompleteChange(field.key, value, option)
              "
              @search="(query) => handleAutoCompleteSearch(field.key, query)"
            />

            <!-- 图片上传 -->
            <view
              v-else-if="field.type === 'image-upload'"
              class="image-upload-container"
            >
              <uni-file-picker
                :value="getFilePickerValue(field.key)"
                :fileMediatype="(field.fileConfig?.accept as any) || 'image'"
                mode="grid"
                :limit="field.fileConfig?.maxCount || 1"
                :sizeType="getFileSizeType(field.fileConfig)"
                :title="field.placeholder"
                :imageStyles="getImageStyles(field.fileConfig, field.key)"
                :delIcon="true"
                @select="handleImageUpload(field, $event)"
                @success="handleImageSuccess(field, $event)"
                @fail="handleImageFail(field, $event)"
                @delete="handleImageDelete(field, $event)"
              />
              <view v-if="field.fileConfig?.tips" class="upload-tips">
                <text class="tips-text">{{ field.fileConfig.tips }}</text>
              </view>
            </view>

            <!-- 文件上传 -->
            <view
              v-else-if="field.type === 'file-upload'"
              class="file-upload-container"
            >
              <uni-file-picker
                :value="getFilePickerValue(field.key)"
                :fileMediatype="(field.fileConfig?.accept as any) || 'all'"
                mode="list"
                :limit="field.fileConfig?.maxCount || 1"
                :title="field.placeholder"
                :delIcon="true"
                @select="handleFileUpload(field, $event)"
                @success="handleFileSuccess(field, $event)"
                @fail="handleFileFail(field, $event)"
                @delete="handleFileDelete(field, $event)"
              />
              <view v-if="field.fileConfig?.tips" class="upload-tips">
                <text class="tips-text">{{ field.fileConfig.tips }}</text>
              </view>
            </view>

            <!-- 通用附件上传 -->
            <XenAttachmentUpload
              v-else-if="field.type === 'attachment-upload'"
              :model-value="getAttachmentValue(field.key)"
              :placeholder="field.placeholder"
              :accept="field.fileConfig?.accept || 'all'"
              :max-count="field.fileConfig?.maxCount || 10"
              :max-size="field.fileConfig?.maxSize || 10"
              :tips="field.fileConfig?.tips"
              :disabled="field.disabled"
              @update:model-value="
                (value) => handleAttachmentChange(field.key, value)
              "
              @upload="(files) => handleAttachmentUpload(field, files)"
              @delete="
                (attachment, index) =>
                  handleAttachmentDelete(field, attachment, index)
              "
              @preview="
                (attachment) => handleAttachmentPreview(field, attachment)
              "
            />

            <!-- 人像相机上传 -->
            <view
              v-else-if="field.type === 'portrait-camera'"
              class="portrait-camera-container"
            >
              <!-- 预览和操作区域 -->
              <view class="portrait-preview-area">
                <!-- 已上传照片的预览 -->
                <view v-if="modelValue[field.key]" class="portrait-preview">
                  <image
                    :src="getImageUrl(modelValue[field.key])"
                    class="portrait-image"
                    mode="aspectFit"
                    @tap="handlePortraitPreview(field)"
                  />
                  <!-- 右上角删除按钮 -->
                  <button
                    class="delete-icon-button"
                    @click="handlePortraitDelete(field)"
                  >
                    <uni-icons
                      type="clear"
                      size="32"
                      color="#727476"
                    ></uni-icons>
                  </button>
                </view>

                <!-- 未上传时的拍摄按钮 -->
                <view v-else class="portrait-capture">
                  <button
                    class="capture-trigger"
                    @click="handlePortraitCapture(field)"
                  >
                    <uni-icons
                      type="camera"
                      size="40"
                      color="#7881de"
                    ></uni-icons>
                    <text class="capture-text">{{ field.placeholder }}</text>
                  </button>
                </view>
              </view>

              <view v-if="field.fileConfig?.tips" class="upload-tips">
                <text class="tips-text">{{ field.fileConfig.tips }}</text>
              </view>
            </view>

            <!-- 特殊处理：加班记录卡片字段 -->
            <view
              v-else-if="
                field.type === 'overtime-card' &&
                field.key === 'overtimeRecords'
              "
            >
              <slot
                name="overtime-records-content"
                :field="field"
                :value="modelValue[field.key]"
                :error="errors[field.key]"
              >
                <!-- 默认显示 -->
                <text class="readonly-text"
                  >请在页面中实现 overtime-records-content 插槽</text
                >
              </slot>
            </view>

            <!-- 自定义字段类型插槽 -->
            <slot
              v-else
              :name="`field-${field.type}`"
              :field="field"
              :value="modelValue[field.key]"
              :error="errors[field.key]"
              :onChange="(value: any) => handleFieldChange(field.key, value)"
              :onBlur="() => handleFieldBlur(field.key)"
            />

            <!-- 错误信息 -->
            <text v-if="errors[field.key]" class="error-message">
              {{ errors[field.key] }}
            </text>
          </view>
        </view>
      </view>

      <!-- 表单底部按钮 -->
      <view v-if="showFooter" class="form-footer">
        <slot name="footer" :formData="modelValue" :errors="errors">
          <!-- 默认按钮布局 -->
          <view
            v-if="footerMode === 'create'"
            class="form-btn cancel-btn"
            @click="handleCancel"
          >
            {{ cancelText }}
          </view>
          <view
            v-if="footerMode === 'create'"
            class="form-btn submit-btn"
            @click="handleSubmit"
          >
            {{ submitText }}
          </view>
          <view
            v-if="footerMode === 'edit'"
            class="form-btn save-btn"
            @click="handleSave"
          >
            {{ saveText }}
          </view>
          <view
            v-if="footerMode === 'edit'"
            class="form-btn submit-btn"
            @click="handleSubmit"
          >
            {{ submitText }}
          </view>
        </slot>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from "vue";
import commonApi from "../api/common";
import XenDepartmentPicker from "./XenDepartmentPicker.vue";
import XenAutoComplete from "./XenAutoComplete.vue";
import XenDatePicker from "./XenDatePicker.vue";
import XenNumberInput from "./XenNumberInput.vue";
import XenPortraitCamera from "./XenPortraitCamera.vue";
import XenAttachmentUpload from "./XenAttachmentUpload.vue";
import XenAppSelector from "./XenAppSelector.vue";
import XenAppDatePicker from "./XenAppDatePicker.vue";

// 字段配置接口
export interface FieldConfig {
  key: string;
  label: string;
  type:
    | "input"
    | "textarea"
    | "number"
    | "picker"
    | "datetime"
    | "date"
    | "native-date"
    | "readonly"
    | "autocomplete"
    | "attachment-upload"
    | string;
  placeholder: string;
  required?: boolean;
  maxlength?: number;
  options?: string[];
  optionsData?: any[]; // picker选项数据（对象数组）
  rangeKey?: string; // picker的显示字段名（当optionsData为对象数组时使用）
  searchApi?: (query: string) => Promise<any[]>; // 自动补全搜索API
  minSearchLength?: number; // 最小搜索长度
  debounceTime?: number; // 防抖时间
  // 原生日期选择器相关属性
  startDate?: string; // 开始日期
  endDate?: string; // 结束日期
  dateFormat?: "YYYY-MM-DD" | "YYYY/MM/DD" | "MM/DD/YYYY"; // 日期格式
  disabled?: boolean; // 是否禁用
  readonly?: boolean; // 是否只读
  // 数字输入框相关属性
  min?: number; // 最小值
  max?: number; // 最大值
  step?: number | string; // 步长
  precision?: number; // 小数位数
  allowNegative?: boolean; // 是否允许负数
  // 额外信息显示功能
  extraInfo?: (value: any, formData?: any) => string; // 计算并显示额外信息
  tips?: string; // 字段提示信息
  // 身份证有效期特殊标识：支持长期有效显示
  supportLongTerm?: boolean;
  [key: string]: any; // 允许扩展属性
}

// 表单分组接口
export interface FormSection {
  key: string;
  title: string;
  fields: FieldConfig[];
}

// Props 定义
interface Props {
  // 基础配置
  title?: string;
  subtitle?: string;
  showHeader?: boolean;
  showFooter?: boolean;

  // 表单配置
  sections: FormSection[];
  modelValue: Record<string, any>;
  errors?: Record<string, string>;

  // 按钮配置
  footerMode?: "create" | "edit" | "custom";
  cancelText?: string;
  saveText?: string;
  submitText?: string;

  // 字段处理器
  fieldHandlers?: Record<string, any>;

  // 身份证有效期显示状态
  idCardExpiryDisplayState?: string;
}

const props = withDefaults(defineProps<Props>(), {
  title: "",
  subtitle: "",
  showHeader: true,
  showFooter: true,
  footerMode: "create",
  cancelText: "取消",
  saveText: "保存",
  submitText: "提交",
  errors: () => ({}),
  fieldHandlers: () => ({}),
});

// Emits 定义
const emit = defineEmits<{
  "update:modelValue": [value: Record<string, any>];
  cancel: [];
  submit: [];
  save: [];
  fieldChange: [fieldKey: string, value: any];
  fieldBlur: [fieldKey: string];
  pickerChange: [fieldKey: string, event: any];
  datetimeChange: [fieldKey: string, event: any];
  departmentPickerChange: [fieldKey: string, value: any, item: any];
  departmentPickerOpen: [];
  departmentPickerClose: [];
  // 时间选择器事件
  dateTimePickerOpen: [];
  dateTimePickerClose: [];
  // 自动补全事件
  autoCompleteChange: [fieldKey: string, value: any, option: any];
  autoCompleteSearch: [fieldKey: string, query: string];
  // 文件上传事件
  imageUpload: [field: FieldConfig, event: any];
  imageSuccess: [field: FieldConfig, event: any];
  imageFail: [field: FieldConfig, event: any];
  imageDelete: [field: FieldConfig, event: any];
  fileUpload: [field: FieldConfig, event: any];
  fileSuccess: [field: FieldConfig, event: any];
  fileFail: [field: FieldConfig, event: any];
  fileDelete: [field: FieldConfig, event: any];
  // 附件上传事件
  attachmentUpload: [field: FieldConfig, files: any[]];
  attachmentDelete: [field: FieldConfig, attachment: any, index: number];
  attachmentPreview: [field: FieldConfig, attachment: any];
}>();

// 字段值变化处理
const handleFieldChange = (fieldKey: string, value: any) => {
  const newValue = { ...props.modelValue, [fieldKey]: value };
  emit("update:modelValue", newValue);
  emit("fieldChange", fieldKey, value);
};

// 字段失焦处理
const handleFieldBlur = (fieldKey: string) => {
  emit("fieldBlur", fieldKey);
};

// 选择器变化处理
const handlePickerChange = (fieldKey: string, event: any) => {
  emit("pickerChange", fieldKey, event);
};

// APP端选择器值变化处理
const handleAppSelectorChange = (
  fieldKey: string,
  value: any,
  field: FieldConfig,
) => {
  // 更新表单数据
  const newValue = { ...props.modelValue, [fieldKey]: value };
  emit("update:modelValue", newValue);
  emit("fieldChange", fieldKey, value);
};

// APP端选择器选项变化处理（含选中的选项对象）
const handleAppSelectorOptionChange = (
  fieldKey: string,
  value: any,
  option: any,
  field: FieldConfig,
) => {
  // 构建一个类似原生picker的事件对象，保持兼容性
  // 需要提供索引值以兼容原有的handlePickerChange逻辑
  const options = field.optionsData || field.options || [];
  let index = 0;

  // 查找当前值在选项中的索引
  if (field.optionsData && field.optionsData.length > 0) {
    // 对象数组格式
    index = field.optionsData.findIndex((item: any) => item.value === value);
  } else if (field.options && field.options.length > 0) {
    // 字符串数组格式
    index = field.options.indexOf(value);
  }

  // 确保索引有效
  if (index < 0) index = 0;

  const pickerEvent = {
    detail: {
      value: index, // 传递索引值，与原生picker保持一致
      option: option,
    },
  };

  // 触发原有的pickerChange事件，保持与原来的行为一致
  emit("pickerChange", fieldKey, pickerEvent);
};

// 日期时间变化处理
const handleDateTimeChange = (fieldKey: string, event: any) => {
  // 更新表单数据
  const newValue = { ...props.modelValue, [fieldKey]: event };
  emit("update:modelValue", newValue);
  emit("datetimeChange", fieldKey, event);

  // 当时间选择发生变化时，延时触发关闭事件，确保操作栏显示
  // 使用延时是因为 @change 事件可能在弹框关闭之前触发
  setTimeout(() => {
    emit("dateTimePickerClose");
  }, 100);
};

// 部门选择器变化处理
const handleDepartmentPickerChange = (
  fieldKey: string,
  value: any,
  item: any,
) => {
  // 触发自定义事件，让父组件处理
  emit("departmentPickerChange", fieldKey, value, item);
};

// 部门选择器弹框打开处理
const handleDepartmentPickerOpen = () => {
  emit("departmentPickerOpen");
};

// 部门选择器弹框关闭处理
const handleDepartmentPickerClose = () => {
  emit("departmentPickerClose");
};

// 时间选择器弹框打开处理
const handleDateTimePickerOpen = () => {
  emit("dateTimePickerOpen");
};

// 时间选择器弹框关闭处理
const handleDateTimePickerClose = () => {
  emit("dateTimePickerClose");
};

// 自动补全变化处理
const handleAutoCompleteChange = (
  fieldKey: string,
  value: any,
  option: any,
) => {
  // 触发自定义事件，让父组件处理
  emit("autoCompleteChange", fieldKey, value, option);
};

// 自动补全搜索处理
const handleAutoCompleteSearch = (fieldKey: string, query: string) => {
  // 触发自定义事件，让父组件处理
  emit("autoCompleteSearch", fieldKey, query);
};

// 文件上传相关方法
const getFilePickerValue = (fieldKey: string) => {
  const fieldValue = props.modelValue[fieldKey];
  if (!fieldValue) return [];

  // 如果是字符串ID（文件ID），需要转换为文件对象用于回显
  if (typeof fieldValue === "string") {
    // 根据字段名确定文件类型和显示名称
    let fileName = "文件";
    if (fieldKey === "idCardFrontPhotoId" || fieldKey === "idCardFrontPhoto") {
      fileName = "身份证正面";
    } else if (
      fieldKey === "idCardBackPhotoId" ||
      fieldKey === "idCardBackPhoto"
    ) {
      fileName = "身份证反面";
    } else if (fieldKey === "photoId") {
      fileName = "个人照片";
    } else if (fieldKey === "veteranCertificateId") {
      fileName = "退伍证图片";
    } else if (
      fieldKey.toLowerCase().includes("photo") ||
      fieldKey.toLowerCase().includes("image")
    ) {
      fileName = "图片";
    }

    return [
      {
        name: fileName,
        url: getImageUrl(fieldValue),
        extname: "jpg",
        size: 0,
        fileID: fieldValue,
      },
    ];
  }

  // 处理单个文件对象（如证明文件字段）
  if (
    fieldValue &&
    typeof fieldValue === "object" &&
    !Array.isArray(fieldValue)
  ) {
    return [
      {
        name: fieldValue.name || "文件",
        url: fieldValue.url || fieldValue.path,
        extname: fieldValue.extname || fieldValue.type?.split("/")[1] || "pdf",
        size: fieldValue.size || 0,
        fileID: fieldValue.id || fieldValue.fileID,
      },
    ];
  }

  // 处理文件数组
  const files = Array.isArray(fieldValue) ? fieldValue : [];
  return files.map((file: any) => ({
    name: file.name || "文件",
    url: file.url || file.path,
    extname: file.extname || file.type?.split("/")[1] || "jpg",
    size: file.size || 0,
    fileID: file.id || file.fileID,
  }));
};

// 获取图片URL - 参考员工档案的实现
const getImageUrl = (fileId: string | null) => {
  if (!fileId) return "";
  return `${import.meta.env.VITE_BASE_URL}/api/_file/getfile/${fileId}`;
};

const getImageStyles = (fileConfig: any, fieldKey: string) => {
  // 身份证照片使用专门的尺寸 - 横向比例更符合身份证实际尺寸
  if (
    fieldKey === "idCardFrontPhoto" ||
    fieldKey === "idCardBackPhoto" ||
    fieldKey === "idCardFrontPhotoId" ||
    fieldKey === "idCardBackPhotoId"
  ) {
    return {
      width: 180,
      height: 120,
      border: { radius: "8px" },
    };
  }

  // 检查是否为身份证类型（通过配置标识）
  if (fileConfig?.isIdCard) {
    return {
      width: 180,
      height: 120,
      border: { radius: "8px" },
    };
  }

  // 个人照片和退伍证照片使用正方形比例
  if (fieldKey === "photoId" || fieldKey === "veteranCertificateId") {
    return {
      width: 100,
      height: 100,
      border: { radius: "8px" },
    };
  }

  // picture-card 类型的图片
  if (fileConfig?.listType === "picture-card") {
    return {
      width: 100,
      height: 100,
      border: { radius: "8px" },
    };
  }

  // 默认图片样式
  return {
    width: 160,
    height: 100,
    border: { radius: "8px" },
  };
};

// 获取文件大小限制类型
const getFileSizeType = (fileConfig: any) => {
  // uni-file-picker的sizeType不支持大小限制，只支持压缩类型
  // 我们使用compressed来减小文件大小，实际大小检查在handleImageUpload中进行
  return ["compressed"] as any;
};

// 图片上传处理
const handleImageUpload = (field: FieldConfig, event: any) => {
  emit("imageUpload", field, event);
};

const handleImageSuccess = (field: FieldConfig, event: any) => {
  // 图片上传成功后，uni-file-picker会自动在其内部管理文件显示
  // 这里主要是转发事件给父组件做其他处理（如OCR识别等）
  emit("imageSuccess", field, event);
};

const handleImageFail = (field: FieldConfig, event: any) => {
  emit("imageFail", field, event);
};

const handleImageDelete = (field: FieldConfig, event: any) => {
  // 身份证照片删除时，直接清空对应字段的值
  if (
    field.fileConfig?.isIdCard ||
    field.key === "idCardFrontPhotoId" ||
    field.key === "idCardBackPhotoId"
  ) {
    const newValue = { ...props.modelValue, [field.key]: "" };
    emit("update:modelValue", newValue);
  }
  emit("imageDelete", field, event);
};

// 文件上传处理
const handleFileUpload = (field: FieldConfig, event: any) => {
  emit("fileUpload", field, event);
};

const handleFileSuccess = (field: FieldConfig, event: any) => {
  emit("fileSuccess", field, event);
};

const handleFileFail = (field: FieldConfig, event: any) => {
  emit("fileFail", field, event);
};

const handleFileDelete = (field: FieldConfig, event: any) => {
  emit("fileDelete", field, event);
};

// 附件上传相关方法
const getAttachmentValue = (fieldKey: string) => {
  const fieldValue = props.modelValue[fieldKey];
  if (!fieldValue) return [];

  // 如果已经是数组格式，直接返回
  if (Array.isArray(fieldValue)) {
    return fieldValue;
  }

  // 如果是单个对象，转换为数组
  if (typeof fieldValue === "object") {
    return [fieldValue];
  }

  return [];
};

const handleAttachmentChange = (fieldKey: string, value: any[]) => {
  const newValue = { ...props.modelValue, [fieldKey]: value };
  emit("update:modelValue", newValue);
};

const handleAttachmentUpload = (field: FieldConfig, files: any[]) => {
  emit("attachmentUpload", field, files);
};

const handleAttachmentDelete = (
  field: FieldConfig,
  attachment: any,
  index: number,
) => {
  emit("attachmentDelete", field, attachment, index);
};

const handleAttachmentPreview = (field: FieldConfig, attachment: any) => {
  emit("attachmentPreview", field, attachment);
};

// 初始化时获取附件文件名（用于编辑页面回显）
const initializeAttachmentFileNames = async () => {
  console.log("🔍 开始初始化附件文件名");

  // 查找所有附件上传字段
  const attachmentFields = props.sections
    .flatMap((section) => section.fields)
    .filter((field) => field.type === "attachment-upload");

  console.log(
    "📁 找到附件字段:",
    attachmentFields.map((f) => f.key),
  );

  for (const field of attachmentFields) {
    const attachments = getAttachmentValue(field.key);
    console.log(`📎 字段 ${field.key} 的附件数据:`, attachments);

    if (attachments.length > 0) {
      // 编辑页面默认需要获取所有附件的文件名
      const updatedAttachments = [...attachments];
      let hasUpdates = false;

      for (let i = 0; i < updatedAttachments.length; i++) {
        const attachment = updatedAttachments[i];
        console.log(`🔗 处理附件 ${i}:`, attachment);

        // 只要有文件ID就获取文件名
        if (attachment.fileID || attachment.id) {
          const fileId = attachment.fileID || attachment.id;

          // 如果已经处理过这个文件ID，跳过
          if (processedFileIds.value.has(fileId)) {
            console.log(`⏭️ 文件ID ${fileId} 已处理过，跳过`);
            continue;
          }

          console.log(`📞 调用API获取文件名，fileId: ${fileId}`);

          if (fileId) {
            try {
              const fileName = await commonApi().GetFileName(fileId);
              console.log(`✅ 获取到文件名: ${fileName}`);

              if (fileName && fileName !== "未知文件") {
                // 从文件名中提取扩展名
                const fileExt = fileName.split(".").pop()?.toLowerCase() || "";
                updatedAttachments[i] = {
                  ...attachment,
                  name: fileName,
                  extname: fileExt, // 更新扩展名
                };
                hasUpdates = true;
                console.log(`📝 更新附件名称: ${fileName}, 扩展名: ${fileExt}`);
              }

              // 标记为已处理
              processedFileIds.value.add(fileId);
            } catch (error) {
              console.error("❌ 获取文件名失败:", error);
              updatedAttachments[i] = { ...attachment, name: "文件" };
              hasUpdates = true;

              // 即使失败也标记为已处理，避免重复尝试
              processedFileIds.value.add(fileId);
            }
          }
        }
      }

      // 如果有更新，触发响应式更新
      if (hasUpdates) {
        console.log(`🔄 更新字段 ${field.key} 的数据:`, updatedAttachments);
        const newValue = {
          ...props.modelValue,
          [field.key]: updatedAttachments,
        };
        emit("update:modelValue", newValue);
      }
    }
  }

  console.log("✨ 附件文件名初始化完成");
};

// 组件挂载时初始化附件文件名
onMounted(async () => {
  await nextTick();
  await initializeAttachmentFileNames();
});

// 防止重复获取文件名的标记
const processedFileIds = ref(new Set<string>());

// 监听 modelValue 变化，当有新的附件数据时自动获取文件名
watch(
  () => props.modelValue,
  async (newValue) => {
    if (newValue) {
      // 检查是否有新的附件需要获取文件名
      const attachmentFields = props.sections
        .flatMap((section) => section.fields)
        .filter((field) => field.type === "attachment-upload");

      let hasNewAttachments = false;

      for (const field of attachmentFields) {
        const attachments = getAttachmentValue(field.key);
        for (const attachment of attachments) {
          const fileId = attachment.fileID || attachment.id;
          if (fileId && !processedFileIds.value.has(fileId)) {
            hasNewAttachments = true;
            break;
          }
        }
        if (hasNewAttachments) break;
      }

      if (hasNewAttachments) {
        console.log("🔄 检测到新的附件数据，获取文件名");
        await nextTick();
        await initializeAttachmentFileNames();
      }
    }
  },
  { deep: true, immediate: false },
);

// 人像相机处理方法
const portraitCameraRef = ref<any>(null);

const handlePortraitCapture = (field: FieldConfig) => {
  // 检查相机权限
  uni.authorize({
    scope: "scope.camera",
    success: () => {
      // 显示相机界面
      showPortraitCamera(field);
    },
    fail: () => {
      uni.showModal({
        title: "需要相机权限",
        content: "请在设置中开启相机权限以使用拍照功能",
        confirmText: "去设置",
        success: (res) => {
          if (res.confirm) {
            uni.openSetting();
          }
        },
      });
    },
  });
};

const showPortraitCamera = (field: FieldConfig) => {
  // 导航到相机页面，由于相机组件需要全屏显示
  uni.navigateTo({
    url: `/pages/portrait-camera/index?fieldKey=${
      field.key
    }&fieldLabel=${encodeURIComponent(field.label)}&maxSize=${
      field.fileConfig?.maxSize || 5
    }`,
    success: () => {
      // 监听相机页面返回的结果
      uni.$once("portrait-camera-result", handlePortraitCameraResult);
    },
  });
};

const handlePortraitCameraResult = (result: any) => {
  if (result && result.success && result.fieldKey && result.fileId) {
    // 对于个人照片，不直接更新表单数据，而是触发验证流程
    if (result.fieldKey === "photoId") {
      // 触发成功事件，让父组件进行人像验证
      const mockField: FieldConfig = {
        key: result.fieldKey,
        label: result.fieldLabel,
        type: "portrait-camera",
        placeholder: "",
      };
      const mockEvent = {
        fileId: result.fileId,
        path: result.path,
        size: result.size,
      };
      emit("imageSuccess", mockField, mockEvent);
    } else {
      // 其他字段正常处理
      const newValue = {
        ...props.modelValue,
        [result.fieldKey]: result.fileId,
      };
      emit("update:modelValue", newValue);

      // 触发成功事件
      const mockField: FieldConfig = {
        key: result.fieldKey,
        label: result.fieldLabel,
        type: "portrait-camera",
        placeholder: "",
      };
      const mockEvent = {
        fileId: result.fileId,
        path: result.path,
        size: result.size,
      };
      emit("imageSuccess", mockField, mockEvent);
    }
  }
};

const handlePortraitRetake = (field: FieldConfig) => {
  handlePortraitCapture(field);
};

const handlePortraitDelete = (field: FieldConfig) => {
  const newValue = { ...props.modelValue, [field.key]: null };
  emit("update:modelValue", newValue);

  // 触发删除事件
  const mockEvent = { field: field.key };
  emit("imageDelete", field, mockEvent);
};

const handlePortraitPreview = (field: FieldConfig) => {
  const fileId = props.modelValue[field.key];
  if (fileId) {
    const imageUrl = getImageUrl(fileId);
    uni.previewImage({
      urls: [imageUrl],
      current: imageUrl,
    });
  }
};

// 按钮事件处理
const handleCancel = () => {
  emit("cancel");
};

const handleSubmit = () => {
  emit("submit");
};

const handleSave = () => {
  emit("save");
};

// 获取禁用状态下的占位符文本
const getDisabledPlaceholder = (field: FieldConfig): string => {
  if (field.key === "originalPositionId") {
    return "请先选择原部门";
  } else if (field.key === "newPositionId") {
    return "请先选择新部门";
  }
  return field.placeholder;
};

// 统一处理picker显示文本：当传入的是ID（GUID）时，优先用optionsData映射为文本
const guidRegex =
  /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
const getPickerDisplay = (field: FieldConfig): string => {
  const value = (props.modelValue as any)[field.key];
  if (!value) return field.placeholder;

  // 如果不是看起来像ID，直接显示
  if (typeof value !== "string" || !guidRegex.test(value)) {
    return value;
  }

  // 映射 optionsData 中的文本
  const options = field.optionsData || [];
  const match = options.find(
    (o: any) => o.value === value || o.Value === value,
  );
  if (match) return match.text || match.Text || value;

  // 兜底：显示原值
  return value;
};

// 获取额外信息显示
const getExtraInfo = (field: FieldConfig): string => {
  if (!field.extraInfo) return "";
  const value = props.modelValue[field.key];
  try {
    return field.extraInfo(value, props.modelValue);
  } catch (error) {
    console.error("计算额外信息时出错:", error);
    return "";
  }
};
</script>

<style lang="scss" scoped>
.xen-dynamic-form-card {
  /* 移除固定高度，适应父容器布局 */
  display: flex;
  flex-direction: column;
  height: 100%;

  /* 只有当显示底部按钮时才添加底部内边距 */
  &.has-footer {
    /* 为固定底部按钮预留准确空间：按钮44px + 上padding16px + 边框1px + 缓冲15px + 安全区域 */
    padding-bottom: calc(50px + constant(safe-area-inset-bottom));
    padding-bottom: calc(50px + env(safe-area-inset-bottom));
  }

  .form-card {
    background: #ffffff;
    border-radius: 16px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    /* 设置为flex容器，占满父容器 */
    flex: 1;
    display: flex;
    flex-direction: column;

    .form-header {
      padding: 20px 24px;
      border-bottom: 1px solid #f0f0f0;

      .form-title {
        font-size: 18px;
        font-weight: 600;
        color: #333;
        display: block;
        margin-bottom: 4px;
      }

      .form-subtitle {
        font-size: 14px;
        color: #666;
      }
    }

    .form-content {
      flex: 1;
      padding: 24px;
      overflow-y: auto;

      .form-section {
        margin-bottom: 24px;

        &:last-child {
          margin-bottom: 0;
        }

        .section-title {
          font-size: 16px;
          font-weight: 500;
          color: #333;
          margin-bottom: 16px;
          position: relative;
          padding-left: 12px;

          &::before {
            content: "";
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 4px;
            height: 16px;
            background: linear-gradient(135deg, #7579f5 0%, #9973f8 100%);
            border-radius: 2px;
          }
        }
      }

      .form-item {
        margin-bottom: 16px;

        &:last-child {
          margin-bottom: 0;
        }

        .form-label {
          display: block;
          font-size: 14px;
          color: #333;
          margin-bottom: 8px;

          .required {
            color: #ff5252;
            margin-right: 4px;
          }
        }

        .form-input,
        .form-textarea,
        .form-picker,
        .form-readonly {
          width: 100%;
          height: 42px;
          border: 1px solid #e0e0e0;
          border-radius: 8px;
          padding: 0 12px;
          font-size: 14px;
          color: #333;
          box-sizing: border-box;
          line-height: 42px;
          transition:
            border-color 0.3s ease,
            background-color 0.3s ease;

          &:focus {
            border-color: #7881de;
            background: #ffffff;
          }

          &::placeholder {
            color: #999;
          }

          &.has-error {
            border-color: #ff5252;
            background: #fff8f8;
          }

          &.disabled,
          &.readonly {
            background: #f5f5f5;
            border-color: #d9d9d9;
            color: #999;
            cursor: not-allowed;
          }

          &.readonly {
            cursor: default;
          }
        }

        .form-readonly {
          background: #f5f5f5;
          border-color: #d9d9d9;
          display: flex;
          align-items: center;

          .readonly-text {
            color: #666;
            font-size: 14px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            width: 100%;

            &.long-term-text {
              color: #666;
              font-weight: normal;
            }
          }
        }

        .form-textarea {
          height: 100px;
          padding: 12px;
          line-height: 1.5;
        }

        .form-picker {
          &.disabled {
            background: #f5f5f5;
            border-color: #d9d9d9;
            cursor: not-allowed;
          }

          .picker-content {
            display: flex;
            align-items: center;
            justify-content: space-between;
            height: 100%;

            .picker-text {
              font-size: 14px;
              color: #333;

              &.disabled {
                color: #999;
              }

              &:empty::before {
                content: "请选择";
                color: #999;
              }
            }
          }
        }

        .datetime-picker-wrapper {
          width: 100%;

          // uni-datetime-picker 样式
          :deep(.uni-datetime-picker) {
            width: 100%;
            height: 42px;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            box-sizing: border-box;
            transition:
              border-color 0.3s ease,
              background-color 0.3s ease;

            &.has-error {
              border-color: #ff5252;
              background: #fff8f8;
            }

            .uni-datetime-picker-text {
              font-size: 14px;
              color: #333;
              padding: 0 12px;
              line-height: 42px;
            }

            .uni-datetime-picker-placeholder {
              color: #999;
            }
          }
        }

        .field-tips {
          font-size: 12px;
          color: #999;
          margin-top: 4px;
          display: block;
          opacity: 1;
          transform: translateY(0);
          transition:
            opacity 0.3s ease,
            transform 0.3s ease;
          animation: fadeInUp 0.3s ease;
        }

        .extra-info {
          font-size: 12px;
          color: #52c41a;
          margin-top: 4px;
          display: block;
          opacity: 1;
          transform: translateY(0);
          transition:
            opacity 0.3s ease,
            transform 0.3s ease;
          animation: fadeInUp 0.3s ease;
        }

        .error-message {
          font-size: 12px;
          color: #ff5252;
          margin-top: 4px;
          display: block;
          opacity: 1;
          transform: translateY(0);
          transition:
            opacity 0.3s ease,
            transform 0.3s ease;
          animation: fadeInUp 0.3s ease;
        }

        @keyframes fadeInUp {
          from {
            opacity: 0;
            transform: translateY(-10px);
          }
          to {
            opacity: 1;
            transform: translateY(0);
          }
        }
      }
    }

    .form-footer {
      /* 固定在屏幕底部 */
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      z-index: 1;

      /* 原有样式 */
      display: flex;
      padding: 16px 24px;
      border-top: 1px solid #f0f0f0;
      background: #ffffff;
      gap: 16px;

      /* 安全区域适配 - 注意顺序：constant在前，env在后 */
      padding-bottom: calc(constant(safe-area-inset-bottom));
      padding-bottom: calc(env(safe-area-inset-bottom));

      /* 增强视觉效果 */
      box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);

      .form-btn {
        flex: 1;
        height: 44px;
        border-radius: 8px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 15px;
        font-weight: 500;
        transition: all 0.2s;

        &:active {
          opacity: 0.8;
        }

        &.cancel-btn {
          background: #f0f0f0;
          color: #666;
        }

        &.save-btn {
          background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
          color: #fff;
          box-shadow: 0 2px 8px rgba(82, 196, 26, 0.3);
        }

        &.submit-btn {
          background: linear-gradient(135deg, #7579f5 0%, #9973f8 100%);
          color: #fff;
          box-shadow: 0 2px 8px rgba(107, 114, 242, 0.3);
        }
      }
    }
  }

  // 文件上传样式
  .image-upload-container,
  .file-upload-container {
    .upload-tips {
      margin-top: 8px;
      padding: 8px 12px;
      background: #f0f8ff;
      border-radius: 4px;
      border-left: 3px solid #1890ff;

      .tips-text {
        font-size: 12px;
        color: #666;
        line-height: 1.4;
      }
    }
  }

  // 人像相机样式
  .portrait-camera-container {
    .portrait-preview-area {
      min-height: 120px;
      border-radius: 8px;
      overflow: hidden;
    }

    .portrait-preview {
      position: relative;
      width: 160px;
      height: 200px;
      border: 2px dashed #d9d9d9;
      border-radius: 8px;
      overflow: hidden;
      background: #fafafa;

      .portrait-image {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .delete-icon-button {
        position: absolute;
        top: 8px;
        right: 8px;
        width: 32px;
        height: 32px;
        border: none;
        background: transparent;
        display: flex;
        align-items: center;
        justify-content: center;

        &::after {
          border: none;
        }

        &:active {
          transform: scale(0.9);
        }
      }
    }

    .portrait-capture {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 160px;
      height: 200px;
      border: 2px dashed #d9d9d9;
      border-radius: 8px;
      background: #fafafa;
      transition: all 0.3s ease;

      &:hover {
        border-color: #7881de;
        background: #f0f2ff;
      }

      .capture-trigger {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 8px;
        background: none;
        border: none;
        padding: 20px;

        &::after {
          border: none;
        }

        .capture-text {
          font-size: 14px;
          color: #666;
        }

        &:active {
          transform: scale(0.95);
        }
      }
    }

    .upload-tips {
      margin-top: 8px;
      padding: 8px 12px;
      background: #f0f8ff;
      border-radius: 4px;
      border-left: 3px solid #1890ff;

      .tips-text {
        font-size: 12px;
        color: #666;
        line-height: 1.4;
      }
    }
  }
}
</style>
